/*=auto=========================================================================

  Portions (c) Copyright 2006 Brigham and Women's Hospital (BWH) All Rights Reserved.

  See COPYRIGHT.txt
  or http://www.slicer.org/copyright/copyright.txt for details.

  Program:   3D Slicer
  Module:    $RCSfile: vtkMRMLColorNode.h,v $
  Date:      $Date: 2006/03/19 17:12:28 $
  Version:   $Revision: 1.0 $

=========================================================================auto=*/

#ifndef __vtkMRMLColorNode_h
#define __vtkMRMLColorNode_h

// MRML includes
#include "vtkMRMLStorableNode.h"

// VTK includes
class vtkLookupTable;
class vtkScalarsToColors;

// Std includes
#include <string>
#include <vector>

/// \brief Abstract MRML node to represent color information.
///
/// Color nodes describe color look up tables. The tables may be pre-generated by
/// Slicer (the label map colors, some default ramps, a random one) or created by
/// a user. More than one model or label volume or editor can access the prebuilt
/// nodes. This is used as a superclass for table based, procedural based, and
/// implicit function based color nodes.
/// All the color names are initialized to \a NoName ("(none)") when the table
/// is created, using the max index of the colors expected to fill the table
/// to set the size of the names array. If the node is being read in from a
/// file, not all of the colors might be present from 0-max, so the color
/// name should remain (none) at those indices.
/// But if the color node is being built up from colors without names, there
/// is a method to init the names from the color RGBA values so that
/// something would be there rather than the default \a NoName which is used
/// to determine that it's a unnamed and probably uninitialized color.
///
/// Subclasses must reimplement GetColor() and GetNumberOfColors().
class VTK_MRML_EXPORT vtkMRMLColorNode : public vtkMRMLStorableNode
{
public:
  static vtkMRMLColorNode *New();
  vtkTypeMacro(vtkMRMLColorNode,vtkMRMLStorableNode);
  void PrintSelf(ostream& os, vtkIndent indent) override;

  //--------------------------------------------------------------------------
  /// MRMLNode methods
  //--------------------------------------------------------------------------

  vtkMRMLNode* CreateNodeInstance() override;

  ///
  /// Set node attributes
  void ReadXMLAttributes( const char** atts) override;

  ///
  /// Write this node's information to a MRML file in XML format.
  void WriteXML(ostream& of, int indent) override;

  ///
  /// Copy the node's attributes to this object
  void Copy(vtkMRMLNode *node) override;

  ///
  /// Get node XML tag name (like Volume, Model)
  const char* GetNodeTagName() override {return "Color";};

  ///
  /// Reset node attributes to the initial state as defined in the constructor.
  /// NOTE:   it preserves values several dynamic attributes that may be set by an application: type, name
  void Reset(vtkMRMLNode* defaultNode) override;

  ///
  ///
  void UpdateScene(vtkMRMLScene *scene) override;

  ///
  /// Set Type to type, then build colors and set names
  virtual void SetType(int type);
  ///
  /// Get for Type
  vtkGetMacro(Type,int);

  /// Set the type to User or File, ones that don't require building
  /// data structures, just setting flags
  void SetTypeToUser();
  void SetTypeToFile();

  void ProcessMRMLEvents ( vtkObject *caller, unsigned long event, void *callData ) override;

  /// Return the lowest and highest integers, for use in looping.
  /// Override in subclasses when more enums are added.
  virtual int GetFirstType () { return this->User; }
  virtual int GetLastType () { return this->File; }

  /// return a text string describing the color look up table type
  virtual const char * GetTypeAsString();

  /// TypeModifiedEvent is generated when the type of the color look up table changes
  enum
  {
      TypeModifiedEvent = 20002
  };

  /// Get name of a color from its index (index is 0-based)
  /// \sa GetColorIndexByName()
  const char *GetColorName(int ind);

  /// Return the index associated with this color name, which can then be used
  /// to get the color. Returns -1 on failure.
  /// \sa GetColorName()
  int GetColorIndexByName(const char *name);

  /// Get the 0'th based \a colorIndex'th name of this color, replacing all
  /// file name sensitive color name characters with safer character(s).
  /// Only alphanumeric characters (A-Z,a-z,0-9) and '-','_','.','(',')','$',
  /// '!','~','#',','%','^','{','}' are supported; '/', '&', '?', '<'
  /// ... are replaced with '_' (or any other substitution string)
  /// While ' '(space) and accents are technically valid file name characters,
  /// they are replaced as an extra precaution.
  /// The color name is truncated to not be longer than 255 characters.
  /// \a subst can be made of invalid characters and be longer than 1 char
  /// \sa GetColorNameWithoutSpaces
  std::string GetColorNameAsFileName(int colorIndex, const char *subst = "_");

  /// \deprecated GetColorNameWithoutSpaces
  /// Get the 0th based nth name of this color, replacing the spaces with
  /// subst
  /// \sa GetColorNameAsFileName
  std::string GetColorNameWithoutSpaces(int ind, const char *subst);

  /// Set the 0th based nth name of this color.
  /// Returns 1 on success, 0 on failure.
  int SetColorName(int ind, const char *name);

  ///
  /// Set the 0th based nth name of this color, replacing the subst character
  /// with spaces. Returns 1 on success, 0 on failure
  int SetColorNameWithSpaces(int ind, const char *name, const char *subst);
  ///
  /// Get the number of colors in the table
  virtual int GetNumberOfColors();

  /// Retrieve the color associated to the index
  /// Must be reimplemented in the derived classes
  /// Return 1 if the color exists, 0 otherwise
  virtual bool GetColor(int ind, double color[4]);

  ///
  /// Name of the file name from which to read color information
  vtkSetStringMacro(FileName);
  vtkGetStringMacro(FileName);

  ///
  /// Most color nodes will implement a look up table, so provide a top level
  /// get method
  virtual vtkLookupTable * GetLookupTable();

  /// Utility function that either returns a vtkLookupTable or a
  /// vtkColorTransferFunction whichever makes more sense.
  /// Returns vtkMRMLColorNode::GetLookupTable() by default. You should
  /// the method if you want it to return something else in subclasses
  virtual vtkScalarsToColors* GetScalarsToColors();

  /// get/set the string used for an unnamed color
  /// "(none)" by default.
  /// \sa SetColorName
  vtkGetStringMacro(NoName);
  vtkSetStringMacro(NoName);

  ///
  /// Get/Set for the flag on names array having been initialized
  vtkGetMacro(NamesInitialised, int);
  vtkSetMacro(NamesInitialised, int);
  vtkBooleanMacro(NamesInitialised, int);
  ///
  /// Set values in the names vector from the colors in the node
  void SetNamesFromColors();

  /// \sa vtkMRMLStorableNode::GetModifiedSinceRead()
  bool GetModifiedSinceRead() override;

  /// The list of valid color node types, added to in subclasses
  /// For backward compatibility, User and File keep the numbers that
  /// were in the ColorTable node
  ///
  /// User - user defined in the GUI
  /// File - read in from file
  enum
  {
    User = 13,
    File = 14,
  };

  /// Helper function for copying lookup tables
  /// It handles special types of lookup tables and fixes
  /// error in vtkLookupTable copy.
  virtual vtkLookupTable* CreateLookupTableCopy();

protected:
  vtkMRMLColorNode();
  ~vtkMRMLColorNode() override;
  vtkMRMLColorNode(const vtkMRMLColorNode&);
  void operator=(const vtkMRMLColorNode&);

  ///
  /// Set values in the names vector from the colors in the node
  virtual bool SetNameFromColor(int index);

  /// Return true if the color index has a "real" name, otherwise return false
  /// if the name is \a NoName (i.e. "(none)") or automatically generated
  /// (i.e. "R=...G=...B=...").
  /// \sa GetNoName()
  virtual bool HasNameFromColor(int index);

  /// Which type of color information does this node hold?
  /// Valid values are in the enumerated list
  int Type;

  ///
  /// A vector of names for the color table elements
  std::vector<std::string> Names;

  ///
  /// A file name to read text attributes from
  char *FileName;

  ///
  /// the string used for an unnamed color
  char *NoName;

  ///
  /// Have the color names been set? Used to do lazy copy of the Names array.
  int NamesInitialised;
};

#endif
